package com.gemini.main.concurrent;


import java.util.concurrent.atomic.AtomicReference;

public class CLHLock implements Lock {

    private AtomicReference<QNode> tail;
    private ThreadLocal<QNode> preNode;
    private ThreadLocal<QNode> myNode;

    public CLHLock() {
        tail = new AtomicReference<QNode>(new QNode());
        myNode = ThreadLocal.withInitial(QNode::new);
        preNode = ThreadLocal.withInitial(() -> null);

    }


    @Override
    public void lock() {
        QNode qnode = myNode.get();
        qnode.locked = true;
        QNode pre = tail.getAndSet(qnode);
        preNode.set(pre);
        while (pre.locked) {
        }

    }

    @Override
    public void unlock() {
        QNode qnode = myNode.get();
        qnode.locked = false;
        myNode.set(preNode.get());
    }

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new MyThread();
        thread.start();

        Thread.sleep(500);
        System.out.println(thread.getState());
        thread.interrupt();
        Thread.sleep(1000);
        System.out.println(thread.isInterrupted());
    }

    static class MyThread extends Thread {
        public void run() {
            synchronized (this){
                try {
                    wait();
                } catch (InterruptedException e) {
                    System.out.println("i am waiting but facing interrupt exception now");
                }
            }
        }
    }
}
